//=========================================================================
// Copyright (C) 2024 The C++ Component Model(COMO) Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//=========================================================================

/**
 * Persistent Memory Library Tests
 */

#include <config.h>
#include <stdio.h>
#include <time.h>
#include "check_common.h"
#include "pmalloc.h"

#define LEAK_SLOTS 1
#define USE_SLOTS 2

#define PM_CAPACITY 1024LL * 1024 * 1024 * 10

TEST(PmallocTest, TestPmrecycle)
{
    //printf("Start checking test using %d leak slots\n", LEAK_SLOTS);
    init_random();
    int fd = open("pmrecycle_ds.dat", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
    ASSERT_GE(fd, 0) << "open file fail";

    void *md = pmalloc_attach(fd, nullptr, PM_CAPACITY, false);
    ASSERT_NE(md, nullptr) << "pmalloc_attach fail";

    long keyidx = -1;
    size_t j;
    void *data = nullptr;
    void *keydata = nullptr;

    for (int cycle = 0;  cycle < 1000;  cycle++) {
        keyidx = random_number(0, USE_SLOTS - 1 + LEAK_SLOTS);
        //printf("key index is %ld, ", keyidx);

        if (keyidx <= USE_SLOTS) {
            keydata = pmalloc_getkey(md, keyidx);
            if (nullptr != keydata) {
                pmfree(md, keydata);
                pmalloc_setkey(md, keyidx, nullptr);
                // printf(ANSI_COLOR_GREEN
                //        "Released original key data at %p! \n" ANSI_COLOR_RESET,
                //        keydata);
            }
            else {
                // printf(ANSI_COLOR_CYAN
                //        "No original key data set in this key slot! "
                //        "\n" ANSI_COLOR_RESET);
            }
        }
        else {
            printf(ANSI_COLOR_MAGENTA "out of range! \n" ANSI_COLOR_RESET);
        }

        j = random_number(1, PM_CAPACITY / 3);  // j = j < 0x4000 ? 0x4000 : j;

        data = pmalloc(md, j);
        if (nullptr != data) {
            // printf(ANSI_COLOR_BLUE
            //        "Allocated a pm block size %zx in %p \n" ANSI_COLOR_RESET,
            //        j, data);
        }
        else {
            break;
        }

        pmalloc_setkey(md, keyidx, data);

    }

    pmalloc_detach(md);
    close(fd);
    //printf("PM Closed.\n");
}

/*原项目在CTest下的测试用例代码*/

// int main() {
//     printf("Start checking test using %d leak slots\n", LEAK_SLOTS);
//     // srand(time(nullptr));
//     init_random();
//     int fd = open("pmrecycle_ds.dat", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
//     if (fd < 0) {
//         printf(ANSI_COLOR_RED "Open test data file failure." ANSI_COLOR_RESET);
//         return 1;
//     }

//     void *md = pmalloc_attach(fd, nullptr, PM_CAPACITY);

//     long keyidx = -1;

//     size_t j;

//     void *data = nullptr, *keydata = nullptr;

//     do {
//         keyidx = random_number(0, USE_SLOTS - 1 + LEAK_SLOTS);
//         printf("key index is %ld, ", keyidx);

//         if (keyidx < USE_SLOTS) {
//             keydata = pmalloc_getkey(md, keyidx);
//             if (nullptr != keydata) {
//                 pmfree(md, keydata);
//                 pmalloc_setkey(md, keyidx, nullptr);
//                 printf(ANSI_COLOR_GREEN
//                        "Released original key data at %p! \n" ANSI_COLOR_RESET,
//                        keydata);
//             } else
//                 printf(ANSI_COLOR_CYAN
//                        "No original key data set in this key slot! "
//                        "\n" ANSI_COLOR_RESET);
//         } else
//             printf(ANSI_COLOR_MAGENTA "out of range! \n" ANSI_COLOR_RESET);

//         j = random_number(1,
//                            PM_CAPACITY / 3);  // j = j < 0x4000 ? 0x4000 : j;

//         data = pmalloc(md, j);

//         if (nullptr != data)
//             printf(ANSI_COLOR_BLUE
//                    "Allocated a pm block size %zx in %p \n" ANSI_COLOR_RESET,
//                    j, data);
//         else
//             break;

//         pmalloc_setkey(md, keyidx, data);

//     } while (1);

//     pmalloc_detach(md);
//     close(fd);
//     printf("PM Closed.\n");
//     return 0;
// }
